//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V1.1.0
#include "spi_bsp.h"
#include "stm32f4xx.h"
#include "stm32f4xx_spi.h"
#include "misc.h"
#include <string.h>
#include <stdlib.h>

#ifndef NULL
#define NULL ((void*)0)
#endif

typedef struct
{
    void (*GPIO_Init_CB)(void);
}WHT_SPI_GPIO_t;

/*SPI总线结构体*/
typedef struct
{
    WHT_SPI_BUS_t Info;       //总线信息
    unsigned int Delay_Count; //延迟时间
    SPI_TypeDef* SPI_BUS;     //总线外设
    WHT_SPI_GPIO_t GPIO;      //总线GPIO
    WHT_SPI_Cache_t* Cache;   //外设缓存,由外部设备提供
	FunctionalState DMA_State;//DMA状态
    WHT_DMA_Config_t DMA_Send_Config;   //DMA发送配置
    WHT_DMA_Config_t DMA_Receive_Config;//DMA接收配置
}WHT_SPI_BUS_Private_t;


static WHT_SPI_BUS_Private_t* WHT_SPI_BUS[6];//SPI总线6个

#define WHT_BUS        ((WHT_SPI_BUS_Private_t*)bus)


/*SPI回调用户的中断函数*/
static void WHT_SPI_BSP_User_IT_Callback(WHT_SPI_BUS_Private_t* BUS)
{
    *(WHT_SPI_BUS_Lock_enum*)&BUS->Info.Mutex = SPI_Unlock;
    if (BUS->Cache->TRx_Finish_IT_CB != NULL)
        BUS->Cache->TRx_Finish_IT_CB();
}

/*SPI DMA发送回调函数*/
static void WHT_SPI_BSP_DMA_Send_Callback(WHT_SPI_BUS_Private_t* BUS)
{
	SPI_I2S_DMACmd(BUS->SPI_BUS, SPI_I2S_DMAReq_Tx, DISABLE);//Close Tx DMA
	if (BUS->DMA_Send_Config.Info->State == TRx_TC)//发送完成
	{
		if (BUS->Cache->Dir == SPI_WO)
		{
			while(SPI_I2S_GetFlagStatus(BUS->SPI_BUS, SPI_I2S_FLAG_BSY) == SET);//死等待发送完成
			SPI_I2S_ReceiveData(BUS->SPI_BUS);                                  //丢掉接收的数据,clear rx_it_over
			if (BUS->Info.Config.NSS == Soft_NSS)
				BUS->Cache->Set_NSS_State_CB(SPI_IO_Hig);
			SPI_Cmd(BUS->SPI_BUS, DISABLE);//Close SPI
			BUS->DMA_State = DISABLE;      //close dma flag
			WHT_SPI_BSP_User_IT_Callback(BUS);
		}
	}
	else if (BUS->DMA_Send_Config.Info->State == TRx_TE)//发送失败
	{
		SPI_I2S_DMACmd(BUS->SPI_BUS, SPI_I2S_DMAReq_Rx, DISABLE);//Close Rx DMA
		if (BUS->Cache->Dir != SPI_WO)
			WHT_DMA_BSP.WHT_Close(&BUS->DMA_Receive_Config);
		SPI_I2S_ReceiveData(BUS->SPI_BUS);                       //丢掉接收的数据,clear rx_it_over
		if (BUS->Info.Config.NSS == Soft_NSS)
			BUS->Cache->Set_NSS_State_CB(SPI_IO_Hig);
		SPI_Cmd(BUS->SPI_BUS, DISABLE);//Close SPI
		BUS->DMA_State = DISABLE;      //close dma flag
		*(WHT_SPI_BUS_State_enum*)&BUS->Info.State = SPI_BUS_Error;//error
		WHT_SPI_BSP_User_IT_Callback(BUS);
	}
}
/*SPI DMA接收回调函数*/
static void WHT_SPI_BSP_DMA_Receive_Callback(WHT_SPI_BUS_Private_t* BUS)
{
	SPI_I2S_DMACmd(BUS->SPI_BUS, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, DISABLE);//Close Tx/Rx DMA
	if (BUS->DMA_Receive_Config.Info->State == TRx_TE)
	{	
		WHT_DMA_BSP.WHT_Close(&BUS->DMA_Receive_Config);
		*(WHT_SPI_BUS_State_enum*)&BUS->Info.State = SPI_BUS_Error;//error
	}
	if (BUS->Info.Config.NSS == Soft_NSS)
		BUS->Cache->Set_NSS_State_CB(SPI_IO_Hig);
	SPI_Cmd(BUS->SPI_BUS, DISABLE);//Close SPI
	BUS->DMA_State = DISABLE;      //close dma flag
	WHT_SPI_BSP_User_IT_Callback(BUS);
}
/*SPI DMA发送接收回调函数*/
static void WHT_SPI_BSP_DMA_Send_Receive_Callback(WHT_SPI_BUS_Private_t* BUS)
{
	SPI_I2S_DMACmd(BUS->SPI_BUS, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, DISABLE);//Close Tx DMA
	WHT_DMA_BSP.WHT_Close(&BUS->DMA_Send_Config);
	if (BUS->Cache->Dir != SPI_WO)
		WHT_DMA_BSP.WHT_Close(&BUS->DMA_Receive_Config);
	SPI_I2S_ReceiveData(BUS->SPI_BUS);                     //丢掉接收的数据,clear rx_it_over
	SPI_I2S_ITConfig(BUS->SPI_BUS, SPI_I2S_IT_ERR, ENABLE);//Close Err Interrupt
	if (BUS->Info.Config.NSS == Soft_NSS)
		BUS->Cache->Set_NSS_State_CB(SPI_IO_Hig);
	SPI_Cmd(BUS->SPI_BUS, DISABLE);//Close SPI
	BUS->DMA_State = DISABLE;
	*(WHT_SPI_BUS_State_enum*)&BUS->Info.State = SPI_Rx_Over_Error;//error
	WHT_SPI_BSP_User_IT_Callback(BUS);
}

/*SPI1 DMA发送回调函数*/
static void WHT_SPI1_BSP_DMA_Send_Callback(void)
{
	WHT_SPI_BSP_DMA_Send_Callback(WHT_SPI_BUS[0]);
}
/*SPI1 DMA接收回调函数*/
static void WHT_SPI1_BSP_DMA_Receive_Callback(void)
{
	WHT_SPI_BSP_DMA_Receive_Callback(WHT_SPI_BUS[0]);
}
/*SPI2 DMA发送回调函数*/
static void WHT_SPI2_BSP_DMA_Send_Callback(void)
{
	WHT_SPI_BSP_DMA_Send_Callback(WHT_SPI_BUS[1]);
}
/*SPI2 DMA接收回调函数*/
static void WHT_SPI2_BSP_DMA_Receive_Callback(void)
{
	WHT_SPI_BSP_DMA_Receive_Callback(WHT_SPI_BUS[1]);
}
/*SPI3 DMA发送回调函数*/
static void WHT_SPI3_BSP_DMA_Send_Callback(void)
{
	WHT_SPI_BSP_DMA_Send_Callback(WHT_SPI_BUS[2]);
}
/*SPI3 DMA接收回调函数*/
static void WHT_SPI3_BSP_DMA_Receive_Callback(void)
{
	WHT_SPI_BSP_DMA_Receive_Callback(WHT_SPI_BUS[2]);
}
/*SPI4 DMA发送回调函数*/
static void WHT_SPI4_BSP_DMA_Send_Callback(void)
{
	WHT_SPI_BSP_DMA_Send_Callback(WHT_SPI_BUS[3]);
}
/*SPI4 DMA接收回调函数*/
static void WHT_SPI4_BSP_DMA_Receive_Callback(void)
{
	WHT_SPI_BSP_DMA_Receive_Callback(WHT_SPI_BUS[3]);
}
/*SPI5 DMA发送回调函数*/
static void WHT_SPI5_BSP_DMA_Send_Callback(void)
{
	WHT_SPI_BSP_DMA_Send_Callback(WHT_SPI_BUS[4]);
}
/*SPI5 DMA接收回调函数*/
static void WHT_SPI5_BSP_DMA_Receive_Callback(void)
{
	WHT_SPI_BSP_DMA_Receive_Callback(WHT_SPI_BUS[4]);
}
/*SPI6 DMA发送回调函数*/
static void WHT_SPI6_BSP_DMA_Send_Callback(void)
{
	WHT_SPI_BSP_DMA_Send_Callback(WHT_SPI_BUS[5]);
}
/*SPI6 DMA接收回调函数*/
static void WHT_SPI6_BSP_DMA_Receive_Callback(void)
{
	WHT_SPI_BSP_DMA_Receive_Callback(WHT_SPI_BUS[5]);
}


/*SPI 发送和接收*/
static void WHT_SPI_BUS_Read_Write(WHT_SPI_BUS_t* bus, WHT_SPI_Cache_t* cache)
{
	unsigned int wait_bus_idle;
	
	*(WHT_SPI_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = SPI_Lock;
	*(WHT_SPI_BUS_State_enum*)&WHT_BUS->Info.State = SPI_No_Error;
	WHT_BUS->Cache = cache;

	SPI_Cmd(WHT_BUS->SPI_BUS, ENABLE);
	if (WHT_BUS->Info.Config.NSS == Soft_NSS)
		WHT_BUS->Cache->Set_NSS_State_CB(SPI_IO_Low);
	else
	{
		wait_bus_idle = WHT_BUS->Delay_Count;
		if (SPI_I2S_GetFlagStatus(WHT_BUS->SPI_BUS, SPI_I2S_FLAG_BSY | SPI_FLAG_MODF) !=  RESET)//其它主设备在通信
		{
			if (wait_bus_idle-- == 0)
			{
				SPI_Cmd(WHT_BUS->SPI_BUS, DISABLE);//close SPI
				*(WHT_SPI_BUS_State_enum*)&WHT_BUS->Info.State = SPI_BUS_Error;
				*(WHT_SPI_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = SPI_Unlock;
				return;
			}
			SPI_Cmd(WHT_BUS->SPI_BUS, ENABLE);
		}
	}
	for (unsigned int i = 0; i < WHT_BUS->Cache->Buffer_Count; i++)
	{
		SPI_I2S_SendData(WHT_BUS->SPI_BUS, WHT_BUS->Cache->Tx_Buffer[i]);
		if (WHT_BUS->Cache->Dir == SPI_WO)
		{
			while (SPI_I2S_GetFlagStatus(WHT_BUS->SPI_BUS, SPI_I2S_FLAG_TXE) == RESET);//TXE事件
		}
		else//SPI_TRx SPI_RO
		{
			while (SPI_I2S_GetFlagStatus(WHT_BUS->SPI_BUS, SPI_I2S_FLAG_RXNE) == RESET);//RXE事件
			WHT_BUS->Cache->Rx_Buffer[i] =(unsigned char)SPI_I2S_ReceiveData(WHT_BUS->SPI_BUS);
		}
	}
	while (SPI_I2S_GetFlagStatus(WHT_BUS->SPI_BUS, SPI_I2S_FLAG_BSY) == SET);
	SPI_I2S_ReceiveData(WHT_BUS->SPI_BUS);//Clear Over
	if (WHT_BUS->Info.Config.NSS == Soft_NSS)
		WHT_BUS->Cache->Set_NSS_State_CB(SPI_IO_Hig);
	SPI_Cmd(WHT_BUS->SPI_BUS, DISABLE);
	*(WHT_SPI_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = SPI_Unlock;
}
/*SPI 中断发送和接收*/
static void WHT_SPI_BUS_Read_Write_IT(WHT_SPI_BUS_t* bus, WHT_SPI_Cache_t* cache)
{
	unsigned int wait_bus_idle;

	*(WHT_SPI_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = SPI_Lock;
	*(WHT_SPI_BUS_State_enum *)&WHT_BUS->Info.State = SPI_No_Error;
	WHT_BUS->Cache = cache;

	SPI_Cmd(WHT_BUS->SPI_BUS, ENABLE);
	if (WHT_BUS->Info.Config.NSS == Soft_NSS)
		WHT_BUS->Cache->Set_NSS_State_CB(SPI_IO_Low);
	else
	{
		wait_bus_idle = WHT_BUS->Delay_Count;
		if (SPI_I2S_GetFlagStatus(WHT_BUS->SPI_BUS, SPI_I2S_FLAG_BSY | SPI_FLAG_MODF) !=  RESET)//其它主设备在通信
		{
			if (wait_bus_idle-- == 0)
			{
				SPI_Cmd(WHT_BUS->SPI_BUS, DISABLE);//close SPI
				*(WHT_SPI_BUS_State_enum*)&WHT_BUS->Info.State = SPI_BUS_Error;
				*(WHT_SPI_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = SPI_Unlock;
				return;
			}
			SPI_Cmd(WHT_BUS->SPI_BUS, ENABLE);
		}
	}
	SPI_I2S_ITConfig(WHT_BUS->SPI_BUS, SPI_I2S_IT_ERR, ENABLE);
	SPI_I2S_ITConfig(WHT_BUS->SPI_BUS, SPI_I2S_IT_RXNE, ENABLE);
	SPI_I2S_ITConfig(WHT_BUS->SPI_BUS, SPI_I2S_IT_TXE, ENABLE);//使能则发送连续但有风险
}
/*SPI DMA发送和接收*/
static void WHT_SPI_BUS_Read_Write_DMA(WHT_SPI_BUS_t* bus, WHT_SPI_Cache_t* cache)
{
    unsigned int wait_bus_idle;

    DMA_InitTypeDef DMA_Send_InitStruct =
    {
        .DMA_Channel            = 0,                          //DMA通道
        .DMA_PeripheralBaseAddr = 0,                          //外设基地址
        .DMA_Memory0BaseAddr    = 0,                          //存储器地址
        .DMA_DIR                = DMA_DIR_MemoryToPeripheral, //M->P
        .DMA_BufferSize         = 0,                          //传输个数
        .DMA_PeripheralInc      = DMA_PeripheralInc_Disable,  //外设地址不递增
        .DMA_MemoryInc          = DMA_MemoryInc_Enable,       //存储器地址递增
        .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,//外设数据大小为字节
        .DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte,    //存储器数据大小为字节，跟外设数据大小相同
        .DMA_Mode               = DMA_Mode_Normal,            //单次传输模式
        .DMA_Priority           = DMA_Priority_Low,           //优先级最低
        .DMA_FIFOMode           = DMA_FIFOMode_Disable,       //FIFO模式
        .DMA_FIFOThreshold      = DMA_FIFOThreshold_1QuarterFull,//FIFO阈值
        .DMA_MemoryBurst        = DMA_MemoryBurst_Single,     //内存突发传输
        .DMA_PeripheralBurst    = DMA_PeripheralBurst_Single, //外设突发传输
    };

    DMA_InitTypeDef DMA_Receive_InitStruct =
    {
        .DMA_Channel            = 0,                          //DMA通道
        .DMA_PeripheralBaseAddr = 0,                          //外设基地址
        .DMA_Memory0BaseAddr    = 0,                          //存储器地址
        .DMA_DIR                = DMA_DIR_PeripheralToMemory, //P->M
        .DMA_BufferSize         = 0,                          //传输个数
        .DMA_PeripheralInc      = DMA_PeripheralInc_Disable,  //外设地址不递增
        .DMA_MemoryInc          = DMA_MemoryInc_Enable,       //存储器地址递增
        .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,//外设数据大小为字节
        .DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte,    //存储器数据大小为字节，跟外设数据大小相同
        .DMA_Mode               = DMA_Mode_Normal,            //单次传输模式
        .DMA_Priority           = DMA_Priority_Low,           //优先级最低
        .DMA_FIFOMode           = DMA_FIFOMode_Disable,       //FIFO模式
        .DMA_FIFOThreshold      = DMA_FIFOThreshold_1QuarterFull,//FIFO阈值
        .DMA_MemoryBurst        = DMA_MemoryBurst_Single,     //内存突发传输
        .DMA_PeripheralBurst    = DMA_PeripheralBurst_Single, //外设突发传输
    };

	*(WHT_SPI_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = SPI_Lock;
	*(WHT_SPI_BUS_State_enum*)&WHT_BUS->Info.State = SPI_No_Error;
	WHT_BUS->Cache = cache;
	if (WHT_BUS->Info.Config.Bit_Wide == SPI_16Bit_Wide)
	{
		DMA_Send_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据大小为字节
		DMA_Send_InitStruct.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;    //存储器数据大小为字节，跟外设数据大小相同
		DMA_Receive_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据大小为字节
		DMA_Receive_InitStruct.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;    //存储器数据大小为字节，跟外设数据大小相同
	}

	DMA_Send_InitStruct.DMA_Channel = WHT_BUS->DMA_Send_Config.Channel;              //DMA通道
	DMA_Send_InitStruct.DMA_PeripheralBaseAddr = (unsigned int)&WHT_BUS->SPI_BUS->DR;//外设基地址
	DMA_Send_InitStruct.DMA_Memory0BaseAddr = (unsigned int)WHT_BUS->Cache->Tx_Buffer;//数据源首地址
	DMA_Send_InitStruct.DMA_BufferSize = WHT_BUS->Cache->Buffer_Count;               //传输数据个数
	WHT_BUS->DMA_Send_Config.DMA_InitStruct = &DMA_Send_InitStruct;
	while (WHT_BUS->DMA_Send_Config.Info->BSP_Mutex == SET);//等待没有外设使用此通道的DMA
	WHT_BUS->DMA_Send_Config.Info->BSP_Mutex = SET;         //DMA通道上锁
	WHT_DMA_BSP.WHT_Config(&WHT_BUS->DMA_Send_Config);      //配置当前DMA

	if (WHT_BUS->Cache->Dir != SPI_WO)
	{
		DMA_Receive_InitStruct.DMA_Channel = WHT_BUS->DMA_Receive_Config.Channel;           //DMA通道
		DMA_Receive_InitStruct.DMA_PeripheralBaseAddr = (unsigned int)&WHT_BUS->SPI_BUS->DR;//外设基地址
		DMA_Receive_InitStruct.DMA_Memory0BaseAddr = (unsigned int)WHT_BUS->Cache->Rx_Buffer;//数据源首地址
		DMA_Receive_InitStruct.DMA_BufferSize = WHT_BUS->Cache->Buffer_Count;               //传输数据个数
		WHT_BUS->DMA_Receive_Config.DMA_InitStruct = &DMA_Receive_InitStruct;
		while (WHT_BUS->DMA_Receive_Config.Info->BSP_Mutex == SET);//等待没有外设使用此通道的DMA
		WHT_BUS->DMA_Receive_Config.Info->BSP_Mutex = SET;         //DMA通道上锁
		WHT_DMA_BSP.WHT_Config(&WHT_BUS->DMA_Receive_Config);      //配置当前DMA
	}

    //检测总线状态
	wait_bus_idle = WHT_BUS->Delay_Count;
	SPI_Cmd(WHT_BUS->SPI_BUS, ENABLE);//Open SPI
	if (WHT_BUS->Info.Config.NSS == Soft_NSS)
		WHT_BUS->Cache->Set_NSS_State_CB(SPI_IO_Low);
	else
	{
		if (SPI_I2S_GetFlagStatus(WHT_BUS->SPI_BUS, SPI_I2S_FLAG_BSY | SPI_FLAG_MODF) !=  RESET)//其它主设备在通信
		{
			if (wait_bus_idle-- == 0)
			{
				if (WHT_BUS->Cache->Dir != SPI_WO)
					WHT_DMA_BSP.WHT_Close(&WHT_BUS->DMA_Receive_Config);//close dma
				WHT_DMA_BSP.WHT_Close(&WHT_BUS->DMA_Send_Config);       //close dma
				SPI_Cmd(WHT_BUS->SPI_BUS, DISABLE);                     //close SPI
				*(WHT_SPI_BUS_State_enum*)&WHT_BUS->Info.State = SPI_BUS_Error;
				*(WHT_SPI_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = SPI_Unlock;
				return;
			}
			SPI_Cmd(WHT_BUS->SPI_BUS, ENABLE);
		}
	}

	WHT_BUS->DMA_State = ENABLE;		
	if (WHT_BUS->Cache->Dir != SPI_WO)
	{
		SPI_I2S_ITConfig(WHT_BUS->SPI_BUS, SPI_I2S_IT_ERR, DISABLE);//close IT Error 一定不能开启
		SPI_I2S_DMACmd(WHT_BUS->SPI_BUS, SPI_I2S_DMAReq_Rx, ENABLE);//使能DMA请求
	}
	SPI_I2S_DMACmd(WHT_BUS->SPI_BUS, SPI_I2S_DMAReq_Tx, ENABLE);    //使能DMA请求
}


/*SPI总线配置*/
static void WHT_SPI_BUS_Config(WHT_SPI_BUS_t* bus)
{
	SPI_InitTypeDef SPI_InitStruct;
	
	/*临时关闭串口*/
	SPI_Cmd(WHT_BUS->SPI_BUS, DISABLE);
	/*SPI相关GPIO初始化*/
    WHT_BUS->GPIO.GPIO_Init_CB();

	switch (WHT_BUS->Info.Config.Work_Mode)
	{
	case SPI_Work_Mode0:SPI_InitStruct.SPI_CPHA =SPI_CPHA_1Edge;SPI_InitStruct.SPI_CPOL =SPI_CPOL_Low; break;
	case SPI_Work_Mode1:SPI_InitStruct.SPI_CPHA =SPI_CPHA_2Edge;SPI_InitStruct.SPI_CPOL =SPI_CPOL_Low; break;
	case SPI_Work_Mode2:SPI_InitStruct.SPI_CPHA =SPI_CPHA_1Edge;SPI_InitStruct.SPI_CPOL =SPI_CPOL_High;break;
	case SPI_Work_Mode3:SPI_InitStruct.SPI_CPHA =SPI_CPHA_2Edge;SPI_InitStruct.SPI_CPOL =SPI_CPOL_High;break;
	}

    /*初始化配置SPI相关寄存器*/
	SPI_InitStruct.SPI_BaudRatePrescaler = WHT_BUS->Info.Config.Clock_Div;
	SPI_InitStruct.SPI_CRCPolynomial     = 7;						      //校验默认值
	SPI_InitStruct.SPI_DataSize          = WHT_BUS->Info.Config.Bit_Wide == SPI_8Bit_Wide ? SPI_DataSize_8b : SPI_DataSize_16b;
	SPI_InitStruct.SPI_Direction         = SPI_Direction_2Lines_FullDuplex;//全双工模式
	SPI_InitStruct.SPI_FirstBit          = WHT_BUS->Info.Config.MSB_LSB == 0 ? SPI_FirstBit_MSB : SPI_FirstBit_LSB;
	SPI_InitStruct.SPI_Mode              = WHT_BUS->Info.Config.Master_Slave == 0 ? SPI_Mode_Master : SPI_Mode_Slave;
	SPI_InitStruct.SPI_NSS               = WHT_BUS->Info.Config.NSS == Soft_NSS ? SPI_NSS_Soft : SPI_NSS_Hard;
	SPI_Init(WHT_BUS->SPI_BUS, &SPI_InitStruct);

	WHT_BUS->Delay_Count = ((((WHT_BUS->Info.Config.Clock_Div >> 3) + 1) << 1) << 0) * (WHT_BUS->Info.Config.Bit_Wide == SPI_8Bit_Wide ? 8 : 16);//延迟时间

	SPI_CalculateCRC(WHT_BUS->SPI_BUS, DISABLE);//close spi crc
	SPI_I2S_ITConfig(WHT_BUS->SPI_BUS, SPI_I2S_IT_TXE, DISABLE);
	SPI_I2S_ITConfig(WHT_BUS->SPI_BUS, SPI_I2S_IT_RXNE, DISABLE);
	SPI_I2S_ITConfig(WHT_BUS->SPI_BUS, SPI_I2S_IT_ERR, DISABLE);

	if (WHT_BUS->Info.Config.NSS == Hard_NSS)/*如果硬件管控NSS，想要释放NSS则需要关闭SPI功能，且必须引脚有上拉电阻*/
		SPI_SSOutputCmd(WHT_BUS->SPI_BUS, ENABLE);
	else
		SPI_NSSInternalSoftwareConfig(WHT_BUS->SPI_BUS, SPI_NSSInternalSoft_Set);
}
/*SPI中断优先级配置*/
static void WHT_SPI_BUS_NVIC_Configuration(WHT_SPI_BUS_t* bus)
{
	/* 配置中断源 */
    if (strcmp(WHT_BUS->Info.Name, WHT_SPI1_Name) == 0)
	{
		NVIC_SetPriority(SPI1_IRQn, WHT_BUS->Info.Config.IT_PreemptionPriority);
		NVIC_EnableIRQ(SPI1_IRQn);
	}
    else if (strcmp(WHT_BUS->Info.Name, WHT_SPI2_Name) == 0)
	{
		NVIC_SetPriority(SPI2_IRQn, WHT_BUS->Info.Config.IT_PreemptionPriority);
		NVIC_EnableIRQ(SPI2_IRQn);
	}
    else if (strcmp(WHT_BUS->Info.Name, WHT_SPI3_Name) == 0)
	{
		NVIC_SetPriority(SPI3_IRQn, WHT_BUS->Info.Config.IT_PreemptionPriority);
		NVIC_EnableIRQ(SPI3_IRQn);
	}
    else if (strcmp(WHT_BUS->Info.Name, WHT_SPI4_Name) == 0)
	{
		NVIC_SetPriority(SPI4_IRQn, WHT_BUS->Info.Config.IT_PreemptionPriority);
		NVIC_EnableIRQ(SPI4_IRQn);
	}
    else if (strcmp(WHT_BUS->Info.Name, WHT_SPI5_Name) == 0)
	{
		NVIC_SetPriority(SPI5_IRQn, WHT_BUS->Info.Config.IT_PreemptionPriority);
		NVIC_EnableIRQ(SPI5_IRQn);
	}
    else if (strcmp(WHT_BUS->Info.Name, WHT_SPI6_Name) == 0)
	{
		NVIC_SetPriority(SPI6_IRQn, WHT_BUS->Info.Config.IT_PreemptionPriority);
		NVIC_EnableIRQ(SPI6_IRQn);
	}
}
/*总线初始化*/
static void WHT_SPI_BUS_Init(WHT_SPI_BUS_t* bus)
{
    if (strcmp(WHT_BUS->Info.Name, WHT_SPI1_Name) == 0)
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
		WHT_BUS->SPI_BUS = SPI1;
    }
    else if (strcmp(WHT_BUS->Info.Name, WHT_SPI2_Name) == 0)
    {
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
        WHT_BUS->SPI_BUS = SPI2;
    }
	else if (strcmp(WHT_BUS->Info.Name, WHT_SPI3_Name) == 0)
	{
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
		WHT_BUS->SPI_BUS = SPI3;
	}
	else if (strcmp(WHT_BUS->Info.Name, WHT_SPI4_Name) == 0)
	{
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI4, ENABLE);
		WHT_BUS->SPI_BUS = SPI4;
	}
	else if (strcmp(WHT_BUS->Info.Name, WHT_SPI5_Name) == 0)
	{
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI5, ENABLE);
		WHT_BUS->SPI_BUS = SPI5;
	}
	else if (strcmp(WHT_BUS->Info.Name, WHT_SPI6_Name) == 0)
	{
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI6, ENABLE);
		WHT_BUS->SPI_BUS = SPI6;
	}
    else
        return;

    *(WHT_SPI_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = SPI_Unlock;
    *(WHT_SPI_BUS_State_enum*)&WHT_BUS->Info.State = SPI_No_Error;    
    WHT_BUS->Cache = NULL;
    WHT_BUS->DMA_Send_Config.IT_Callback = NULL;
    WHT_BUS->DMA_Receive_Config.IT_Callback = NULL;
    WHT_BUS->DMA_State = DISABLE;

	/*注册DMA*/
    if (strcmp(WHT_BUS->Info.Name, WHT_SPI1_Name) == 0)
    {
		WHT_BUS->DMA_Send_Config.Stream = Stream_SPI1_TX_1;
		WHT_BUS->DMA_Send_Config.Channel = Channel_SPI1_TX_1;
		WHT_BUS->DMA_Send_Config.IT_Callback = WHT_SPI1_BSP_DMA_Send_Callback;      //DMA Callback
		WHT_BUS->DMA_Receive_Config.Stream = Stream_SPI1_RX_1;
		WHT_BUS->DMA_Receive_Config.Channel = Channel_SPI1_RX_1;
		WHT_BUS->DMA_Receive_Config.IT_Callback = WHT_SPI1_BSP_DMA_Receive_Callback;//DMA Callback
    }
    else if (strcmp(WHT_BUS->Info.Name, WHT_SPI2_Name) == 0)
    {
		WHT_BUS->DMA_Send_Config.Stream = Stream_SPI2_TX;
		WHT_BUS->DMA_Send_Config.Channel = Channel_SPI2_TX;
		WHT_BUS->DMA_Send_Config.IT_Callback = WHT_SPI2_BSP_DMA_Send_Callback;      //DMA Callback
		WHT_BUS->DMA_Receive_Config.Stream = Stream_SPI2_RX;
		WHT_BUS->DMA_Receive_Config.Channel = Channel_SPI2_RX;
		WHT_BUS->DMA_Receive_Config.IT_Callback = WHT_SPI2_BSP_DMA_Receive_Callback;//DMA Callback
    }
	else if (strcmp(WHT_BUS->Info.Name, WHT_SPI3_Name) == 0)
	{
		WHT_BUS->DMA_Send_Config.Stream = Stream_SPI3_TX_1;
		WHT_BUS->DMA_Send_Config.Channel = Channel_SPI3_TX_1;
		WHT_BUS->DMA_Send_Config.IT_Callback = WHT_SPI3_BSP_DMA_Send_Callback;      //DMA Callback
		WHT_BUS->DMA_Receive_Config.Stream = Stream_SPI3_RX_1;
		WHT_BUS->DMA_Receive_Config.Channel = Channel_SPI3_RX_1;
		WHT_BUS->DMA_Receive_Config.IT_Callback = WHT_SPI3_BSP_DMA_Receive_Callback;//DMA Callback
	}

	else if (strcmp(WHT_BUS->Info.Name, WHT_SPI4_Name) == 0)
	{
		WHT_BUS->DMA_Send_Config.Stream = Stream_SPI4_TX_1;
		WHT_BUS->DMA_Send_Config.Channel = Channel_SPI4_TX_1;
		WHT_BUS->DMA_Send_Config.IT_Callback = WHT_SPI4_BSP_DMA_Send_Callback;      //DMA Callback
		WHT_BUS->DMA_Receive_Config.Stream = Stream_SPI4_RX_1;
		WHT_BUS->DMA_Receive_Config.Channel = Channel_SPI4_RX_1;
		WHT_BUS->DMA_Receive_Config.IT_Callback = WHT_SPI4_BSP_DMA_Receive_Callback;//DMA Callback
	}
	else if (strcmp(WHT_BUS->Info.Name, WHT_SPI5_Name) == 0)
	{
		WHT_BUS->DMA_Send_Config.Stream = Stream_SPI5_TX_1;
		WHT_BUS->DMA_Send_Config.Channel = Channel_SPI5_TX_1;
		WHT_BUS->DMA_Send_Config.IT_Callback = WHT_SPI5_BSP_DMA_Send_Callback;      //DMA Callback
		WHT_BUS->DMA_Receive_Config.Stream = Stream_SPI5_RX_1;
		WHT_BUS->DMA_Receive_Config.Channel = Channel_SPI5_RX_1;
		WHT_BUS->DMA_Receive_Config.IT_Callback = WHT_SPI5_BSP_DMA_Receive_Callback;//DMA Callback
	}
	else if (strcmp(WHT_BUS->Info.Name, WHT_SPI6_Name) == 0)
	{
		WHT_BUS->DMA_Send_Config.Stream = Stream_SPI6_TX;
		WHT_BUS->DMA_Send_Config.Channel = Channel_SPI6_TX;
		WHT_BUS->DMA_Send_Config.IT_Callback = WHT_SPI6_BSP_DMA_Send_Callback;      //DMA Callback
		WHT_BUS->DMA_Receive_Config.Stream = Stream_SPI6_RX;
		WHT_BUS->DMA_Receive_Config.Channel = Channel_SPI6_RX;
		WHT_BUS->DMA_Receive_Config.IT_Callback = WHT_SPI6_BSP_DMA_Receive_Callback;//DMA Callback
	}	
    else
        return;
	WHT_DMA_BSP.WHT_Register(&WHT_BUS->DMA_Send_Config);
    WHT_DMA_BSP.WHT_Register(&WHT_BUS->DMA_Receive_Config);

	WHT_SPI_BUS_NVIC_Configuration(bus);
	WHT_SPI_BUS_Config(bus);
}


/*注册SPI总线*/
static WHT_SPI_BUS_t* WHT_SPI_BUS_Register(char* name, WHT_SPI_BUS_Config_t* config, void (*gpio_init_callback)(void))
{
    char Pos;

    if ((strcmp(name, WHT_SPI1_Name) == 0) && (WHT_SPI_BUS[0] == NULL))
        Pos = 0;
    else if ((strcmp(name, WHT_SPI2_Name) == 0) && (WHT_SPI_BUS[1] == NULL))
        Pos = 1;
    else if ((strcmp(name, WHT_SPI3_Name) == 0) && (WHT_SPI_BUS[2] == NULL))
        Pos = 2;
	else if ((strcmp(name, WHT_SPI4_Name) == 0) && (WHT_SPI_BUS[3] == NULL))
        Pos = 3;
	else if ((strcmp(name, WHT_SPI5_Name) == 0) && (WHT_SPI_BUS[4] == NULL))
        Pos = 4;
	else if ((strcmp(name, WHT_SPI6_Name) == 0) && (WHT_SPI_BUS[5] == NULL))
        Pos = 5;
	else
        return NULL;

    WHT_SPI_BUS[Pos] = malloc(sizeof(WHT_SPI_BUS_Private_t));
    if (WHT_SPI_BUS[Pos])
    {
        WHT_SPI_BUS[Pos]->Info.Name = name;
        memcpy(&WHT_SPI_BUS[Pos]->Info.Config, config, sizeof(WHT_SPI_BUS_Config_t));
        WHT_SPI_BUS[Pos]->GPIO.GPIO_Init_CB = gpio_init_callback;
        WHT_SPI_BUS_Init((WHT_SPI_BUS_t*)WHT_SPI_BUS[Pos]);
        return (WHT_SPI_BUS_t*)WHT_SPI_BUS[Pos];
    }
    return NULL;
}
/*注销软件SPI总线*/
static void WHT_SPI_BUS_Unregister(WHT_SPI_BUS_t* bus)
{
    for (size_t i = 0; i < sizeof(WHT_SPI_BUS) / sizeof(WHT_SPI_BUS[0]); i++)
    {
        if (WHT_SPI_BUS[i] == WHT_BUS)
        {
            WHT_SPI_BUS[i] = NULL;
            free(WHT_BUS);
			break;
        }
    }
}


/*全局常量*/
const WHT_SPI_BUS_OPS_t WHT_SPI_BUS_OPS =
{
    .Register       = WHT_SPI_BUS_Register,
    .Unregister     = WHT_SPI_BUS_Unregister,
    //.Set_Rate     = WHT_SPI_BUS_Set_Rate,
    .Read_Write     = WHT_SPI_BUS_Read_Write,
	.Read_Write_IT  = WHT_SPI_BUS_Read_Write_IT,
	.Read_Write_DMA = WHT_SPI_BUS_Read_Write_DMA,
};



/*SPI中断回调函数*/
static void WHT_SPI_BSP_IRQHandler(WHT_SPI_BUS_Private_t* BUS, unsigned int* tx_count, unsigned int* rx_count)
{
#if 1
	/*这个非连续发送数据，相比连续发送数据更安全。这个不怕被高优先级长时间打断，TXE中断必须关闭*/
	if (SPI_I2S_GetITStatus(BUS->SPI_BUS, SPI_I2S_IT_TXE) == SET)//TXE事件
	{
		SPI_I2S_ITConfig(BUS->SPI_BUS, SPI_I2S_IT_TXE, DISABLE);
		if (BUS->Cache->Dir == SPI_RO)
			SPI_I2S_SendData(BUS->SPI_BUS, 0xff);
		else
			SPI_I2S_SendData(BUS->SPI_BUS, BUS->Cache->Tx_Buffer[(*tx_count)++]);
	}
	if (SPI_I2S_GetITStatus(BUS->SPI_BUS, SPI_I2S_IT_RXNE) == SET)//RXE事件
	{
		if (BUS->Cache->Dir == SPI_WO)//发送
			SPI_I2S_ReceiveData(BUS->SPI_BUS);//丢掉接收的数据
		else//if((BUS->Cache->Dir == SPI_TRx) || (BUS->Cache->Dir == SPI_RO))//接收
			BUS->Cache->Rx_Buffer[(*rx_count)++] =(unsigned char)SPI_I2S_ReceiveData(BUS->SPI_BUS);
		if(*tx_count != BUS->Cache->Buffer_Count)
			SPI_I2S_SendData(BUS->SPI_BUS, BUS->Cache->Tx_Buffer[(*tx_count)++]);
		else
		{
			if (BUS->Info.Config.NSS == Soft_NSS)
				BUS->Cache->Set_NSS_State_CB(SPI_IO_Hig);
			SPI_I2S_ITConfig(BUS->SPI_BUS, SPI_I2S_IT_TXE, DISABLE);
			SPI_I2S_ITConfig(BUS->SPI_BUS, SPI_I2S_IT_RXNE, DISABLE);
			SPI_I2S_ITConfig(BUS->SPI_BUS, SPI_I2S_IT_ERR, DISABLE);
			SPI_Cmd(BUS->SPI_BUS, DISABLE);
			*tx_count = *rx_count = 0;
			WHT_SPI_BSP_User_IT_Callback(BUS);
		}
	}
#else//SPI速度快点就会导致不是连续的数据流了
/*
这个可以连续发送数据，即时钟连续状态，可以让SPI高效工作。TXE中断必须打开
这个怕接收到数据了，刚好被高优先级的打断并且时间较长导致接收缓存区溢出,丢失数据的问题
如果接收缓冲区溢出。
*/
	if (SPI_I2S_GetITStatus(BUS->SPI_BUS, SPI_I2S_IT_RXNE) == SET)//RXE事件
	{
		if (BUS->Cache->Dir == SPI_WO)//MASTER只写
			SPI_I2S_ReceiveData(BUS->SPI_BUS);//丢掉接收的数据
		else//if ((BUS->Cache->Dir == SPI_TRx) || (BUS->Cache->Dir == SPI_RO))//接收
			BUS->Cache->Rx_Buffer[*rx_count] =(unsigned char)SPI_I2S_ReceiveData(BUS->SPI_BUS);
		(*rx_count)++;
		if (*rx_count == BUS->Cache->Rx_Count)
		{
			if (BUS->Cache->NSS == Soft_NSS)
				*BUS->Cache->Sort_NSS = Hig;
			SPI_I2S_ITConfig(BUS->SPI_BUS, SPI_I2S_IT_RXNE, DISABLE);
			SPI_I2S_ITConfig(BUS->SPI_BUS, SPI_I2S_IT_ERR, DISABLE);
			SPI_I2S_ITConfig(BUS->SPI_BUS, SPI_I2S_IT_TXE, DISABLE);
			SPI_Cmd(BUS->SPI_BUS, DISABLE);
			*rx_count = 0;
			WHT_SPI_BSP_User_IT_Callback(BUS);
		}
	}
	if (SPI_I2S_GetITStatus(BUS->SPI_BUS, SPI_I2S_IT_TXE) == SET)//TXE事件
	{
		if (BUS->Cache->Dir == SPI_RO)
			SPI_I2S_SendData(BUS->SPI_BUS, 0xff);
		else
			SPI_I2S_SendData(BUS->SPI_BUS, BUS->Cache->Tx_Buffer[(*tx_count)++]);
		if (*tx_count == BUS->Cache->Buffer_Count)
		{
			SPI_I2S_ITConfig(BUS->SPI_BUS, SPI_I2S_IT_TXE, DISABLE);
			*tx_count = 0;
		}
	}
#endif
	if (SPI_I2S_GetFlagStatus(BUS->SPI_BUS, SPI_FLAG_CRCERR | SPI_FLAG_MODF | SPI_I2S_FLAG_OVR) == SET)//ERROR
	{
		SPI_I2S_ITConfig(BUS->SPI_BUS, SPI_I2S_IT_TXE, DISABLE);
		SPI_I2S_ITConfig(BUS->SPI_BUS, SPI_I2S_IT_RXNE, DISABLE);
		SPI_I2S_ITConfig(BUS->SPI_BUS, SPI_I2S_IT_ERR, DISABLE);
		if (BUS->DMA_State == ENABLE)
		{
			WHT_SPI_BSP_DMA_Send_Receive_Callback(BUS);
		}
		else
		{
			if (SPI_I2S_GetFlagStatus(BUS->SPI_BUS, SPI_I2S_FLAG_OVR) == SET)
			{
				SPI_I2S_ReceiveData(BUS->SPI_BUS);//丢掉接收的数据
				*(WHT_SPI_BUS_State_enum*)&BUS->Info.State = SPI_Rx_Over_Error;
			}
			else if (SPI_I2S_GetFlagStatus(BUS->SPI_BUS, SPI_FLAG_MODF) == SET)
			{
				SPI_I2S_ReceiveData(BUS->SPI_BUS);//丢掉接收的数据
				*(WHT_SPI_BUS_State_enum*)&BUS->Info.State = SPI_BUS_Error;
			}
			else if (SPI_I2S_GetFlagStatus(BUS->SPI_BUS, SPI_FLAG_CRCERR) == SET)//no crc func
			{
				SPI_I2S_ClearFlag(BUS->SPI_BUS, SPI_FLAG_CRCERR);
				*(WHT_SPI_BUS_State_enum*)&BUS->Info.State = SPI_CRC_Error;
			}
			if (BUS->Info.Config.NSS == Soft_NSS)
				BUS->Cache->Set_NSS_State_CB(SPI_IO_Hig);
			SPI_Cmd(BUS->SPI_BUS, DISABLE);
			WHT_SPI_BSP_User_IT_Callback(BUS);
		}
	}
}

/*SPI1 中断服务程序*/
void SPI1_IRQHandler(void)
{
	static unsigned int tx_count = 0;
	static unsigned int rx_count = 0;

	WHT_SPI_BSP_IRQHandler(WHT_SPI_BUS[0], &tx_count, &rx_count);
}
/*SPI2 中断服务程序*/
void SPI2_IRQHandler(void)
{
	static unsigned int tx_count = 0;
	static unsigned int rx_count = 0;

	WHT_SPI_BSP_IRQHandler(WHT_SPI_BUS[1], &tx_count, &rx_count);
}
/*SPI3 中断服务程序*/
void SPI3_IRQHandler(void)
{
	static unsigned int tx_count = 0;
	static unsigned int rx_count = 0;

	WHT_SPI_BSP_IRQHandler(WHT_SPI_BUS[2], &tx_count, &rx_count);
}
/*SPI4 中断服务程序*/
void SPI4_IRQHandler(void)
{
	static unsigned int tx_count = 0;
	static unsigned int rx_count = 0;

	WHT_SPI_BSP_IRQHandler(WHT_SPI_BUS[3], &tx_count, &rx_count);
}
/*SPI5 中断服务程序*/
void SPI5_IRQHandler(void)
{
	static unsigned int tx_count = 0;
	static unsigned int rx_count = 0;

	WHT_SPI_BSP_IRQHandler(WHT_SPI_BUS[4], &tx_count, &rx_count);
}
/*SPI6 中断服务程序*/
void SPI6_IRQHandler(void)
{
	static unsigned int tx_count = 0;
	static unsigned int rx_count = 0;

	WHT_SPI_BSP_IRQHandler(WHT_SPI_BUS[5], &tx_count, &rx_count);
}
